热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

烤鸭|本文_Spring之Bean的生命周期详解

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Spring之Bean的生命周期详解相关的知识,希望对你有一定的参考价值。   通过前面多个接口的介绍了解了Bean对象生命周期相关的方法&#xff0

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Spring之Bean的生命周期详解相关的知识,希望对你有一定的参考价值。


  通过前面多个接口的介绍了解了Bean对象生命周期相关的方法,本文就将这些接口的方法串起来,来了解Bean的完整的生命周期。而介绍Bean的生命周期也是面试过程中经常会碰到的一个问题,如果不注意就跳坑里啦~~



Spring之Bean对象的初始化和销毁方法
Spring之InitializingBean接口和DisposableBean接口介绍
Spring之Aware接口介绍
Spring之InstantiationAwareBeanPostProcessor接口介绍
Spring之BeanFactoryPostProcessor接口介绍
Spring之BeanPostProcessor(后置处理器)介绍



建议:看此文前请将上面相关的内容熟悉下,便于理解下面的内容。


文章目录


  • Bean生命周期
    • 一、调用过程
    • 二、生命周期方法说明
    • 三、演示
      • 1.BeanFactoryPostProcessor接口
      • 2.BeanPostProcessor接口
      • 3.InstantiationAwareBeanPostProcessor接口
      • 4.BeanNameAware,BeanFactoryAware等Aware接口
      • 5.InitializingBean,DisposableBean接口
      • 6.@PostConstruct和@PreDestroy注解
      • 7.init-method,destroy-method
      • 8.测试

    • 四、Bean对象生命周期总结



Bean生命周期

一、调用过程


二、生命周期方法说明


接口方法说明
BeanFactoryPostProcessorpostProcessBeanFactory在Bean对象实例化之前执行, 通过beanFactory可以获取bean的定义信息, 并可以修改bean的定义信息。这点是和BeanPostProcessor最大区别
BeanPostProcessorpostProcessBeforeInitialization实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务
postProcessAfterInitialization实例化、依赖注入、初始化完毕时执行
InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation在方法实例化之前执行,返回结果为null正常执行,返回结果如果不为null则会跳过相关方法而进入初始化完成后的流程
postProcessAfterInstantiation在方法实例化之后执行,返回结果true才会执行postProcessPropertyValues方法
postProcessPropertyValues可以用来修改Bean中属性的内容
InitializingBeanafterPropertiesSet初始化的方法
DisposableBeandestroy容器销毁前的回调方法
AwaresetXXX感知对应Spring容器的内容
@PostConstruct标注在方法头部,表示初始化的方法
@PreDestroy标注在方法头部,表示销毁前回调的方法
init-method属性指定初始化的方法
destory-method属性指定销毁前的回调方法

三、演示


1.BeanFactoryPostProcessor接口

  该接口中的方法是最先执行的。在Bean实例化之前执行

/**
* 自定义BeanFactoryPostProcessor
*
* @author dengp
*
*/

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor
/**
* 本方法在Bean对象实例化之前执行,
* 通过beanFactory可以获取bean的定义信息,
* 并可以修改bean的定义信息。这点是和BeanPostProcessor最大区别
*/

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException

System.out.println("****** BeanFactoryPostProcessor 开始执行了");
/*String[] names = beanFactory.getBeanDefinitionNames();
for (String name : names)
if("user".equals(name))

BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name);
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
// MutablePropertyValues如果设置了相关属性,可以修改,如果没有设置则可以添加相关属性信息
if(propertyValues.contains("name"))
propertyValues.addPropertyValue("name", "bobo");
System.out.println("修改了属性信息");


*/

System.out.println("******* BeanFactoryPostProcessor 执行结束了");



2.BeanPostProcessor接口

  该接口中定义了两个方法,分别在Bean对象实例化及装配后在初始化的前后执行

/**
* 自定义BeanPostProcessor实现类
* BeanPostProcessor接口的作用是:
* 我们可以通过该接口中的方法在bean实例化、配置以及其他初始化方法前后添加一些我们自己的逻辑
* @author dengp
*
*/

public class MyBeanPostProcessor implements BeanPostProcessor
/**
* 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务
* 注意:方法返回值不能为null
* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象
* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中
*/

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
if("user".equals(beanName))
System.out.println(">>后置处理器 before方法:"+bean+"\\t"+beanName);


// 可以根据beanName不同执行不同的处理操作
return bean;

/**
* 实例化、依赖注入、初始化完毕时执行
* 注意:方法返回值不能为null
* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象
* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中
*/

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
if("user".equals(beanName))
System.out.println("<<后置处理器after方法:"&#43;bean&#43;"\\t"&#43;beanName);

// 可以根据beanName不同执行不同的处理操作
return bean;



3.InstantiationAwareBeanPostProcessor接口

  该接口是BeanPostProcessor接口的子接口&#xff0c;所以该接口肯定具有BeanPostProcessor接口的功能&#xff0c;同时又定义了三个自己的接口&#xff0c;这三个接口是在Bean实例化前后执行的方法。

/**
* 自定义处理器
* &#64;author dengp
*
*/

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor
/**
* BeanPostProcessor接口中的方法
* 在Bean的自定义初始化方法之前执行
* Bean对象已经存在了
*/

&#64;Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
// TODO Auto-generated method stub
if("user".equals(beanName))
System.out.println("【---InstantiationAwareBeanPostProcessor---】 postProcessBeforeInitialization");


return bean;

/**
* BeanPostProcessor接口中的方法
* 在Bean的自定义初始化方法执行完成之后执行
* Bean对象已经存在了
*/

&#64;Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
if("user".equals(beanName))
System.out.println("【--InstantiationAwareBeanPostProcessor----】 postProcessAfterInitialization");

return bean;

/**
* InstantiationAwareBeanPostProcessor中自定义的方法
* 在方法实例化之前执行 Bean对象还没有
*/

&#64;Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException
if("user".equals(beanName))
System.out.println("【--InstantiationAwareBeanPostProcessor----】postProcessBeforeInstantiation");

return null;

/**
* InstantiationAwareBeanPostProcessor中自定义的方法
* 在方法实例化之后执行 Bean对象已经创建出来了
*/

&#64;Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException
if("user".equals(beanName))
System.out.println("【--InstantiationAwareBeanPostProcessor----】postProcessAfterInstantiation");

return true;

/**
* InstantiationAwareBeanPostProcessor中自定义的方法
* 可以用来修改Bean中属性的内容
*/

&#64;Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean,
String beanName) throws BeansException
if("user".equals(beanName))
System.out.println("【--InstantiationAwareBeanPostProcessor----】postProcessPropertyValues--->");

return pvs;



4.BeanNameAware,BeanFactoryAware等Aware接口

  Aware接口是用来让对象感知当前的IOC环境


5.InitializingBean,DisposableBean接口

  这两个接口是Bean初始化及销毁回调的方法。


6.&#64;PostConstruct和&#64;PreDestroy注解

package com.dpb.pojo;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
/**
* 实现InitializingBean和DisposableBean接口
* &#64;author dengp
*
*/

public class User implements InitializingBean,DisposableBean,BeanNameAware,BeanFactoryAware
private int id;

private String name;
//感知本对象在Spring容器中的id属性
private String beanName;
// 感知本对象所属的BeanFactory对象
private BeanFactory factory;

public User()
System.out.println("构造方法被执行了...User 被实例化");

public int getId()
return id;

public void setId(int id)
this.id &#61; id;

public String getName()
return name;

public void setName(String name)
System.out.println("《注入属性》注入name属性"&#43;name);
this.name &#61; name;

public String getBeanName()
return beanName;


&#64;Override
public String toString()
return "User [id&#61;" &#43; id &#43; ", name&#61;" &#43; name &#43; ", beanName&#61;" &#43; beanName &#43; "]";

/**
* bean对象销毁前的回调方法
*/

&#64;Override
public void destroy() throws Exception
// TODO Auto-generated method stub
System.out.println("《DisposableBean接口》destory ....");

/**
* 初始化的方法
*/

&#64;Override
public void afterPropertiesSet() throws Exception
System.out.println("初始化:《InitializingBean接口》afterPropertiesSet....");

&#64;Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException
// TODO Auto-generated method stub
System.out.println("【BeanFactoryAware接口】setBeanFactory");
this.factory &#61; beanFactory;

&#64;Override
public void setBeanName(String name)
System.out.println("【BeanNameWare接口】setBeanName");
this.beanName &#61; name;

public BeanFactory getFactory()
return factory;

/**
* 也是个初始化的方法
*/

&#64;PostConstruct
public void postConstruct()
System.out.println("初始化:【&#64;PostConstruct】执行了...");

/**
* 销毁前的回调方法
*/

&#64;PreDestroy
public void preDestory()
System.out.println("【&#64;preDestory】执行了...");

/**
* 初始化的方法
* 通过bean标签中的 init-method属性指定
*/

public void start()
System.out.println("初始化:【init-method】方法执行了....");


/**
* 销毁前的回调方法
* 通过bean标签中的 destory-method属性指定
*/

public void stop()
System.out.println("【destory-method】方法执行了....");



7.init-method&#xff0c;destroy-method


<beans xmlns&#61;"http://www.springframework.org/schema/beans"
xmlns:xsi&#61;"http://www.w3.org/2001/XMLSchema-instance"
xmlns:context&#61;"http://www.springframework.org/schema/context"
xsi:schemaLocation&#61;"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"
>


<context:annotation-config/>
<bean class&#61;"com.dpb.pojo.User" id&#61;"user" init-method&#61;"start" destroy-method&#61;"stop" >
<property name&#61;"name" value&#61;"波波烤鸭">property>
bean>


<bean class&#61;"com.dpb.processor.MyBeanPostProcessor"/>



<bean class&#61;"com.dpb.processor.MyInstantiationAwareBeanPostProcessor">bean>

<bean class&#61;"com.dpb.factoryprocessor.MyBeanFactoryPostProcessor"/>
beans>

8.测试

&#64;Test
public void test1()
System.out.println("Spring容器开始加载....");
ClassPathXmlApplicationContext ac &#61; new ClassPathXmlApplicationContext("applicationContext.xml");
User user &#61; ac.getBean(User.class);
System.out.println("---------------"&#43;user);
ac.registerShutdownHook();
System.out.println("Spring容器卸载完成....");

输出结果

Spring容器开始加载....
三月 04, 2019 11:14:38 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext&#64;707f7052: startup date [Mon Mar 04 23:14:38 CST 2019]; root of context hierarchy
三月 04, 2019 11:14:39 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
****** BeanFactoryPostProcessor 开始执行了
******* BeanFactoryPostProcessor 执行结束了
【--InstantiationAwareBeanPostProcessor----】postProcessBeforeInstantiation
构造方法被执行了...User 被实例化
【--InstantiationAwareBeanPostProcessor----】postProcessAfterInstantiation
【--InstantiationAwareBeanPostProcessor----】postProcessPropertyValues--->
《注入属性》注入name属性波波烤鸭
【BeanNameWare接口】setBeanName
【BeanFactoryAware接口】setBeanFactory
>>后置处理器 before方法:User [id&#61;0, name&#61;波波烤鸭, beanName&#61;user] user
【---InstantiationAwareBeanPostProcessor---】 postProcessBeforeInitialization
初始化:【&#64;PostConstruct】执行了...
初始化:《InitializingBean接口》afterPropertiesSet....
初始化:【init-method】方法执行了....
<<后置处理器after方法:User [id&#61;0, name&#61;波波烤鸭, beanName&#61;user] user
【--InstantiationAwareBeanPostProcessor----】 postProcessAfterInitialization
---------------User [id&#61;0, name&#61;波波烤鸭, beanName&#61;user]
Spring容器卸载完成....
三月 04, 2019 11:14:39 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext&#64;707f7052: startup date [Mon Mar 04 23:14:38 CST 2019]; root of context hierarchy
【&#64;preDestory】执行了...
《DisposableBean接口》destroy ....
【destory-method】方法执行了....

四、Bean对象生命周期总结


  1. 如果实现了BeanFactoryPostProcessor接口&#xff0c;那么在容器启动的时候&#xff0c;该接口中的postProcessBeanFactory方法可以修改Bean中元数据中的信息。该方法是在实例化对象之前执行
  2. 如果实现了InstantiationAwareBeanPostProcessor接口&#xff0c;那么在实例化Bean对象之前会调用postProcessBeforeInstantiation方法&#xff0c;该方法如果返回的不为null则会直接调用postProcessAfterInitialization方法&#xff0c;而跳过了Bean实例化后及初始化前的相关方法&#xff0c;如果返回null则正常流程&#xff0c;postProcessAfterInstantiation在实例化成功后执行&#xff0c;这个时候对象已经被实例化&#xff0c;但是该实例的属性还未被设置&#xff0c;都是null。因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素&#xff08;因为还有一个因素是mbd.getDependencyCheck()&#xff09;&#xff1b;如果该方法返回false,并且不需要check&#xff0c;那么postProcessPropertyValues就会被忽略不执行&#xff1b;如果返回true, postProcessPropertyValues就会被执行,postProcessPropertyValues用来修改属性&#xff0c;在初始化方法之前执行。
  3. 如果实现了Aware相关的结果&#xff0c;那么相关的set方法会在初始化之前执行。
  4. 如果实现了BeanPostProcessor接口&#xff0c;那么该接口的方法会在实例化后的初始化方法前后执行。
  5. 如果实现了InitializingBean接口则在初始化的时候执行afterPropertiesSet
  6. 如果指定了init-method属性则在初始化的时候会执行指定的方法。
  7. 如果指定了&#64;PostConstruct则在初始化的时候会执行标注的方法。
  8. 到此对象创建完成
  9. 当对象需要销毁的时候。
  10. 如果实现了DisposableBean接口会执行destroy方法
  11. 如果指定了destroy-method属性则会执行指定的方法
  12. 如果指定了&#64;PreDestroy注解则会执行标注的方法

~ 这就是Bean对象的生命周期了。有问题的欢迎留言


推荐阅读
  • 本文详细探讨了在微服务架构中,使用Feign进行远程调用时出现的请求头丢失问题,并提供了具体的解决方案。重点讨论了单线程和异步调用两种场景下的处理方法。 ... [详细]
  • 深入解析Spring Boot自动配置机制
    本文旨在深入探讨Spring Boot的自动配置机制,特别是如何利用配置文件进行有效的设置。通过实例分析,如Http编码自动配置,我们将揭示配置项的具体作用及其背后的实现逻辑。 ... [详细]
  • Eclipse 中 JSP 开发环境配置指南
    本文详细介绍了如何在 Eclipse 集成开发环境中配置 JSP 运行环境,包括必要的软件下载、Tomcat 服务器的配置以及常见问题的解决方法。 ... [详细]
  • EasyMock实战指南
    本文介绍了如何使用EasyMock进行单元测试,特别是当测试对象的合作者依赖于外部资源或尚未实现时。通过具体的示例,展示了EasyMock在模拟对象行为方面的强大功能。 ... [详细]
  • 本文探讨如何利用Java反射技术来模拟Webwork框架中的URL解析过程。通过这一实践,读者可以更好地理解Webwork及其后续版本Struts2的工作原理,尤其是它们在MVC架构下的角色。 ... [详细]
  • 利用YAML配置Resilience4J的Circuit Breaker
    本文探讨了Resilience4j作为现代Java应用程序中不可或缺的容错工具,特别介绍了如何通过YAML文件配置Circuit Breaker以提高服务的弹性和稳定性。 ... [详细]
  • 掌握Mosek矩阵运算,轻松应对优化挑战
    本篇文章继续深入探讨Mosek学习笔记系列,特别是矩阵运算部分,这对于优化问题的解决至关重要。通过本文,您将了解到如何高效地使用Mosek进行矩阵初始化、线性代数运算及约束域的设定。 ... [详细]
  • 尾花|花萼_相关性Correlations 皮尔逊相关系数(pearson)和斯皮尔曼等级相关系数(spearman)
    尾花|花萼_相关性Correlations 皮尔逊相关系数(pearson)和斯皮尔曼等级相关系数(spearman) ... [详细]
  • Spring Cloud学习指南:深入理解微服务架构
    本文介绍了微服务架构的基本概念及其在Spring Cloud中的实现。讨论了微服务架构的主要优势,如简化开发和维护、快速启动、灵活的技术栈选择以及按需扩展的能力。同时,也探讨了微服务架构面临的挑战,包括较高的运维要求、分布式系统的复杂性、接口调整的成本等问题。最后,文章提出了实施微服务时应遵循的设计原则。 ... [详细]
  • 本文介绍了如何利用Java中的URLConnection类来实现基本的网络爬虫功能,包括向目标网站发送请求、接收HTML响应、解析HTML以提取所需信息,并处理可能存在的递归爬取需求。 ... [详细]
  • Spring Cloud Config 使用 Vault 作为配置存储
    本文探讨了如何在Spring Cloud Config中集成HashiCorp Vault作为配置存储解决方案,基于Spring Cloud Hoxton.RELEASE及Spring Boot 2.2.1.RELEASE版本。文章还提供了详细的配置示例和实践建议。 ... [详细]
  • 深入解析Android中的SQLite数据库使用
    本文详细介绍了如何在Android应用中使用SQLite数据库进行数据存储。通过自定义类继承SQLiteOpenHelper,实现数据库的创建与版本管理,并提供了具体的学生信息管理示例代码。 ... [详细]
  • ▶书中第四章部分程序,包括在加上自己补充的代码,有边权有向图的邻接矩阵,FloydWarshall算法可能含负环的有边权有向图任意两点之间的最短路径●有边权有向图的邻接矩阵1 ... [详细]
  • 本文将详细介绍如何在ThinkPHP6框架中实现多数据库的部署,包括读写分离的策略,以及如何通过负载均衡和MySQL同步技术优化数据库性能。 ... [详细]
  • Java 架构:深入理解 JDK 动态代理机制
    代理模式是 Java 中常用的设计模式之一,其核心在于代理类与委托类共享相同的接口。代理类主要用于为委托类提供预处理、过滤、转发及后处理等功能,以增强或改变原有功能的行为。 ... [详细]
author-avatar
ruirui2011幸福
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有